home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_100
/
137_01
/
llsup.asm
< prev
next >
Wrap
Assembly Source File
|
1985-03-09
|
5KB
|
209 lines
;
; llsup.asm
;
; a component of lsup.c
;
; Copyright 1984 (c) A. Skjellum. All rights reserved.
;
; version of 25-Mar-84
;
; This routine makes no assumptions about the behavior of the
; C compiler in use.
;
; all procedures are "near"
;
dseg segment para public 'data'
dseg ends
cseg segment para public 'code'
assume cs:cseg,ds:dseg
;
; linc: increment a long pointer by 1 byte
;
; expects: es:bx with long pointer to increment
; returns: pointer incremented.
; consumes: es, bx, f, ax
;
public linc
linc proc near
inc bx ; increment low part of word
or bx,bx ; is it zero now?
jnz linc_exit ; no, we are done
mov ax,es
add ax,1000h ; another 64k of paragraphs
mov es,ax ; store back to es
linc_exit:
ret ; return
linc endp
;
; ldec: decrement a long pointer by 1 byte
;
; expects: es:bx with long pointer to decrement
; returns: pointer decremented.
; consumes: es, bx, f, ax
;
public ldec
ldec proc near
or bx,bx ; zero currently ?
dec bx ; decrement it
jnz ldec_exit ; just decrement low end and exit...
mov ax,es ; get segment register
sub ax,1000h ; remove 64k of paragraphs
mov es,ax ; store back to es
ldec_exit:
ret ; return
ldec endp
;
; ladd: add a constant to a long pointer
;
; expects: es:bx with long pointer's original value
; ax with unsigned constant to be added
; returns: pointer with constant added
; consumes: es, bx, f, ax
;
public ladd
ladd proc near
add bx,ax ; add in offset
jnc ladd_exit ; no carry, so we are done.
mov ax,es
add ax,1000h ; add 64k of paragraphs
mov es,ax ; and store back to es
ladd_exit:
ret
ladd endp
;
; lsub: subtract a constant from a long pointer
;
; expects: es:bx with long pointer's original value
; ax with unsigned constant to be subtracted
; returns: pointer with constant subtracted
; consumes: es, bx, f, ax
;
public lsub
lsub proc near
sub bx,ax ; subtract offset
jnb lsub_exit ; no borrow, so we are done.
mov ax,es
sub ax,1000h ; subtract 64k of paragraphs
mov es,ax ; and store back to es
lsub_exit:
ret
lsub endp
;
; lsum: add a signed offset to a long pointer
;
; expects: es:bx with long pointer
; ax with signed offset
; returns: pointer with constant added (signed)
; consumes: es, bx, f, ax
;
public lsum
lsum proc near
or ax,ax ; negative?
jm lsum_neg
call ladd ; do addition
ret ; and exit
lsum_neg:
and ax,07fffh ; and out sign flag
jnz lsum_neg_ok
mov ax,8000h ; -32768 value (don't treat as 0)
lsum_neg_ok:
call lsub
ret
lsum endp
;
; lcopy: copy from one long pointer to another,
; up to 1024k bytes of data
;
; expects: ds:si with src address
; es:di with dest address
; ds|cx with length (dx is high order, cx is low order)
;
; returns: block copied
; ds, es intact
; consumes: ax, cx, f
;
;
; this routine uses a copy downward method, to produce
; correct copying for overlapping regions
;
public lcopy
lcopy proc near
;
; convert dx into segment form:
;
push dx ; save original form of dx
push cx ; save low order of long count
and dx,15 ; smallest meaningful value
xchg dh,dl ; switch upper and lower parts
mov cl,4
shl dh,cl ; effect is shift left by 12 bits
pop cx ; and recover low order of long count
;
mov ax,es
add ax,dx
mov es,ax
mov ax,ds
add ax,dx
mov ds,ax ; gross adjustment of segments
pop dx ; recover original form of dx
;
add di,cx ; adjust dest. ptr to end of area
jnc no_dest_adj
mov ax,es
add ax,1000h ; add offset
mov es,ax ; and store back to segment register
no_dest_adj:
;
; do same work for source pointer:
;
add si,cx ; do the addition
jnc no_mor_adj ; no more adjustment needed if no carry
mov ax,ds
add ax,1000h ; do the adjustment
mov ds,ax ; and store back to ds
;
; at this stage:
;
; es:di is at the last byte of the dest. area
; ds:si is at the last byte of the src. area
;
no_mor_adj:
std ; set direction flag for moves
lc_loop:
or si,si ; is si zero ?
lodsb ; get byte ds:[si], decrement si
jnz no_ds_adj ; no need to adjust if non-zero at start
mov ax,ds
sub ax,1000h
mov ds,ax ; adjust pointer for next load
no_ds_adj:
or di,di ; is di zero ?
stosb ; set byte es:[di] = al, decrement di
jnz no_es_adj ; no need to adjust if non-zero at start
mov ax,es
sub ax,1000h
mov es,ax ; adjust pointer for next store
no_es_adj:
loop lc_loop ; copy whole block (--cx, jnz lc_loop)
dec dx ; work on outer loop
or dx,dx
jnz lc_loop ; loop over dx counts too
;
; we are done
;
inc si
inc di ; restore to original calling values
ret ; exit
lcopy endp
cseg ends
end